﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Elderos.Highlight.Search;
using Elderos.Ontology;

namespace Elderos.Highlight.Rules
{
    [RankingRule("ChainLength", RuleType.Text)]
    public class RuleChainLength : RankingRule
    {
        public RuleChainLength(IOntologyData ontology) : base(ontology)
        {
        }

        private static HashSet<string> _prepositions = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
                                                           {
                                                               "as",
                                                               "at",
                                                               "but",
                                                               "by",
                                                               "for",
                                                               "from",
                                                               "in",
                                                               "into",
                                                               "of",
                                                               "on",
                                                               "onto",
                                                               "over",
                                                               "per",
                                                               "to",
                                                               "up",
                                                               "via",
                                                               "with"
                                                           };

        private readonly string[] _factorNames =
        {
            "ChainLength_RightCount",
            "ChainLength_LeftCount"
        };

#pragma warning disable 1998
        protected async override Task<Dictionary<TextEntity, IRuleResult>> InnerRank(HighlightResult highlightResult)
#pragma warning restore 1998
        {
            var result = new Dictionary<TextEntity, IRuleResult>();
            var tokens = highlightResult.Tokens;

            foreach (var position in highlightResult.Positions.SelectMany(x => x.SubpositionsFlattened))
            {
                if (position.IsFake) continue;

                int rightCount = 0;
                for (int i = position.TokenInterval.Last + 1; i < tokens.Length; i++)
                {
                    var token = tokens[i];
                    if (token.Length <= 2)
                    {
                        if (char.IsPunctuation(token, 0) && token[0] != ',')
                            break;
                        continue;
                    }
                    if (!token.IsWord) continue;
                    if (token.IsChainElement)
                        rightCount++;
                    else if (_prepositions.Contains(token))
                        continue;
                    else
                        break;
                }

                int leftCount = 0;
                for (int i = position.TokenInterval.First - 1; i >= 0; i--)
                {
                    var token = tokens[i];
                    if (token.Length <= 2)
                    {
                        if (token.IsPunctuation && token != ",")
                            break;
                        continue;
                    }
                    if (token.IsChainElement)
                        leftCount++;
                    else if (_prepositions.Contains(token))
                        continue;
                    else
                        break;
                }

                foreach (var textEntity in position.Entities)
                {
                    result.Add(textEntity, new ArrayResult(_factorNames, new double[] {rightCount, leftCount}));
                }
            }
            return result;
        }

        public override IRuleResult EmptyResult
        {
            get { return new ArrayResult(_factorNames, new[]{0D, 0});}
        }
    }
}
